home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1997 July
/
EnigmA AMIGA RUN 20 (1997)(G.R. Edizioni)(IT)[!][issue 1997-07 & 08][EAR-CD IV].iso
/
earcd
/
biz
/
dbase
/
db3_4src.lha
/
db3.4
/
Design.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-29
|
34KB
|
1,410 lines
#include <exec/types.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/gadtools.h>
#include <proto/utility.h>
#include <proto/exec.h> /* CopyMem() */
#include <string.h> /* strcpy */
#include <stdlib.h> /* abs() macro */
#include "Design.h"
#include "dbGUI.h"
#include "dbparser.h"
#include "Toolbox.h"
#include "DesignGUI.h"
#include "Version.h"
#include "Pointers.h"
#include <stdio.h> // Diagnostics
/*
* Externs to make the new GadToolsBox interface work
* Remove "static" from these in DesignGUI.c
*/
extern struct Gadget *VisGadgets[];
extern struct Window *VisWnd;
extern struct NewMenu DesignNewMenu[];
extern struct Menu *DesignMenus;
#define CURSORWIDTH 3
#define DRAGTRESHOLD 6
#define TOGGLE_LED *(UBYTE *)0xbfe001 ^= 2 /* Debug */
/* Handy macros */
#define FLOOR(x,f) if ((x)<(f)) (x) = (f)
/* Return codes from GadToolBox handlers */
#define RET_OK 1
#define RET_CANCEL 2
extern WORD LastLeftEdge;
extern WORD LastTopEdge; /* For nice layoutswitching */
extern void UpdateWindow(struct Pro *Pr);
extern void UpdateDragBar(struct Pro *Pr);
typedef int Bool; /* A char would be smaller, but will produce non-cast warnings */
typedef struct {
struct VisFldInfo *vf;
Bool after; /* Has cursor passed field? (to the left or right of field) */
} Cursor;
struct EasyStruct ES_ViewDesignHelp =
{
sizeof(struct EasyStruct),
0,
(STRPTR)"View design",
(STRPTR) "\n"
"The purpose of this part of db is to allow you to add, edit, rearrange\n"
"and remove visual fields (gadgets) in the current view in a simple way\n"
"by using common mouse and key operations (db will write the RFF code).\n"
"\n"
"You pick new visual fields from the toolbox to the right. They may\n"
"later be edited with a simple doubleclick. To Resize and move them\n"
"around, point at them and drag the mouse (the right border of any visual\n"
"field is resize-sensitive).\n"
"\n"
"You can cut, copy and paste visual fields as expected and there is\n"
"also an undo to help you out.\n"
"\n"
"Visual fields are either separated by a space, tab, newline or double\n"
"newline. Use the keyboard to add and remove these separators.\n"
"\n"
"In this release you still need to use a text editor to specify the\n"
"INTERNAL fields, but that's simple; just write all names in one line,\n"
"separate them with tabs, add a newline, save it and load it into db.\n"
"\n"
"See the documentation for more information. Have fun!",
(STRPTR)"Ok"
};
/**********************************************************************/
/* Globals */
/**********************************************************************/
Cursor Crsr;
struct VisFldInfo *Selected; /* The selected field that has a rubberband */
int DragCnt = 0; /* Non-zero if dragging Selected. */
Bool Sizing = FALSE;
struct Window *ToolBox = NULL;
/* GadToolBox handlers uses global variables */
extern struct Pro *CurrentPro;
struct VisFldInfo *Vf;
extern char *RFFTagNames[];
/* The clipboard */
struct VisFldInfo *Clip = NULL;
/**********************************************************************/
/* Support functions */
/**********************************************************************/
struct VisFldInfo *PrevVisFldInfo(struct Layout *Lay, struct VisFldInfo *vf)
{
struct VisFldInfo *t = Lay->FirstVisFldInfo;
if (t == vf) return NULL;
for (; t; t = t->Next) if (t->Next == vf) return t;
return NULL; /* Safety */
}
static void InitCursor(struct Layout *Lay, Cursor *crsr)
{
crsr->vf = Lay->FirstVisFldInfo;
crsr->after = FALSE;
}
static void GetCursorPosition(Cursor *crsr, WORD *x, WORD *y)
{
/* Return position of cursor in (x,y) coords */
if (crsr->vf) {
*y = crsr->vf->Pos.YOffset;
*x = crsr->vf->Pos.XOffset;
*x += (crsr->after) ? crsr->vf->Pos.Width + CURSORWIDTH : -2*CURSORWIDTH;
}
else {
*x = OffX + FontX; /* As in CalcAllPos() */
*y = OffY + (FontY >> 1); /* As in CalcAllPos() */
}
}
static int PreviousPosition(struct Layout *Lay, Cursor *crsr)
{
/* Position cursor one step to the left (maybe up) */
/* Return FALSE if this is not possible */
struct VisFldInfo *vf;
if (!crsr->vf) return FALSE; /* No gadgets at all */
if (crsr->after) {
crsr->after = FALSE;
return TRUE;
}
else if (vf = PrevVisFldInfo(Lay, crsr->vf)) {
crsr->vf = vf;
crsr->after = TRUE;
return TRUE;
}
return FALSE;
}
static int NextPosition(struct Layout *Lay, Cursor *crsr)
{
/* Position cursor one step to the right (maybe down) */
/* Return FALSE if this is not possible */
if (!crsr->vf) return FALSE; /* No gadgets at all */
if (!crsr->after) {
crsr->after = TRUE;
return TRUE;
}
else if (crsr->vf->Next) {
crsr->vf = crsr->vf->Next;
crsr->after = FALSE;
return TRUE;
}
return FALSE;
}
static void DisplayCursor(struct RastPort *rp, WORD x, WORD y)
{
/* Draws a cursor in complement colour at given position */
/* Deletes cursor at old position automatically */
/* Specify a negative coordinate in either x or y to remove cursor */
/* DisplayCursor assumes a locked cursorheight */
static WORD oldx = -1, oldy = -1;
SetDrMd(rp, COMPLEMENT);
if (oldx>=0 && oldy>=0)
RectFill(rp, oldx, oldy, oldx+CURSORWIDTH-1, oldy+FontY+STRGADFRAMESHEIGHT-1);
if (x>=0 && y>=0)
RectFill(rp, x, y, x+CURSORWIDTH-1, y+FontY+STRGADFRAMESHEIGHT-1);
oldx = x;
oldy = y;
}
static void Rubberband(struct RastPort *rp, WORD left, WORD top, WORD width, WORD height, char handle)
{
/* Draws a border rectangle in complement colour. Adds a handle square if "handle" is TRUE */
/* Deletes old rubberband automatically */
/* Specify a negative coordinate in either left or top to remove rubberband */
static WORD oldleft = -1, oldtop = -1, oldwidth=-1, oldheight=-1, oldhandle = 0;
SetDrMd(rp, COMPLEMENT);
left--; top--; width++; height++;
if (oldleft>=0 && oldtop>=0) {
Move(rp, oldleft, oldtop);
Draw(rp, oldleft+oldwidth, oldtop);
Draw(rp, oldleft+oldwidth, oldtop+oldheight);
Draw(rp, oldleft, oldtop+oldheight);
Draw(rp, oldleft, oldtop);
if (oldhandle) { /* Draw a 3x4 square in the middle of the right border */
RectFill(rp, oldleft+oldwidth+1, oldtop+(oldheight>>1), oldleft+oldwidth+4, oldtop+(oldheight>>1)+2);
}
}
if (left>=0 && top>=0) {
Move(rp, left, top);
Draw(rp, left+width, top);
Draw(rp, left+width, top+height);
Draw(rp, left, top+height);
Draw(rp, left, top);
if (handle) { /* Draw a 3x4 square in the middle of the right border */
RectFill(rp, left+width+1, top+(height>>1), left+width+4, top+(height>>1)+2);
}
}
oldleft = left; oldtop = top; oldwidth = width; oldheight = height; oldhandle = handle;
}
void FollowMouse(struct Layout *Lay, WORD mx, WORD my)
{
/* Moves the cursor to the position that is nearest to (x,y) */
Cursor nearest;
WORD x,y;
WORD nx, ny;
if (!Crsr.vf) return;
while (PreviousPosition(Lay, &Crsr)); /* Go to the beginning */
nearest = Crsr;
GetCursorPosition(&nearest, &nx, &ny);
while (NextPosition(Lay, &Crsr)) {
GetCursorPosition(&Crsr, &x, &y);
if (abs(my-y) < abs(my-ny)) {
nearest = Crsr;
GetCursorPosition(&nearest, &nx, &ny);
}
if (abs(my-y) == abs(my-ny))
if (abs(mx-x) < abs(mx-nx)) {
nearest = Crsr;
GetCursorPosition(&nearest, &nx, &ny);
}
}
Crsr = nearest;
DisplayCursor(Lay->Window->RPort, nx, ny);
}
static struct VisFldInfo *VisFldHit(struct Layout *Lay, WORD x, WORD y)
{
/* Returns the address of the VisFldInfo that is hit by (x,y) */
struct VisFldInfo *vf = NULL;
for (vf = Lay->FirstVisFldInfo; vf; vf = vf->Next) {
if (x >= vf->Pos.XOffset && x < vf->Pos.XOffset+vf->Pos.Width &&
y >= vf->Pos.YOffset && y < vf->Pos.YOffset+vf->Pos.Height)
break;
}
return vf;
}
static Bool SizeHit(struct VisFldInfo *hit, WORD mouseX)
{
/* Return true if mouse is close to the right border of the "hit" field */
return (hit && (hit->Pos.XOffset + hit->Pos.Width - mouseX) < 5);
}
void SelectVisFld(struct Layout *Lay, struct VisFldInfo *vf)
{
if (Selected = vf) {
struct Space *sp = &Selected->Pos;
Rubberband(Lay->Window->RPort, sp->XOffset, sp->YOffset, sp->Width, sp->Height, 0);
}
else {
Rubberband(Lay->Window->RPort, -1, -1, -1, -1, 0);
}
}
static struct VisFldInfo *RemoveVisFldInfo(struct Layout *Lay, struct VisFldInfo *oldvf)
{
/* Remove oldvf from the layout and handle all side effects this may have */
struct VisFldInfo *prev;
if (!oldvf) return NULL;
prev = PrevVisFldInfo(Lay, oldvf);
if (prev) {
prev->Next = oldvf->Next;
if (oldvf->VisSep == '\n' || oldvf->VisSep == '\f') { /* end of line */
prev->VisSep = oldvf->VisSep;
WriteVisTags(prev); /* Update RFF tags in vf */
}
}
else Lay->FirstVisFldInfo = oldvf->Next;
/* Handle cursor and rubberband */
if (Crsr.vf == oldvf) {
if (Crsr.vf->Next) Crsr.vf = Crsr.vf->Next;
else Crsr.vf = prev; /* This might be NULL, and that's ok */
}
SelectVisFld(Lay, NULL);
return oldvf;
}
static void InsertVisFldInfo(struct Layout *Lay, struct VisFldInfo *vf)
{
/* Insert vf in the layout and handle all side effects this may have */
/* vf is placed at the cursor position */
struct VisFldInfo **link_here;
if (!Lay->FirstVisFldInfo) link_here = &Lay->FirstVisFldInfo;
else if (Crsr.after) {
link_here = &Crsr.vf->Next;
vf->VisSep = Crsr.vf->VisSep;
Crsr.vf->VisSep = ' ';
WriteVisTags(vf);
WriteVisTags(Crsr.vf);
}
else {
struct VisFldInfo *prevvf = PrevVisFldInfo(Lay, Crsr.vf);
if (!prevvf) link_here = &Lay->FirstVisFldInfo;
else link_here = &prevvf->Next;
vf->VisSep = ' ';
}
/* Link */
vf->Next = *link_here;
*link_here = vf;
// SelectVisFld(Lay, vf); /* Now, it's easy to spot the new field */
}
int DeleteUndo(struct Layout *Lay)
{
struct VisFldInfo *vf,*nextvf;
for (vf = Lay->FirstUndoVisFldInfo; vf; vf=nextvf) {
nextvf = vf->Next;
DeleteVisFldInfo(vf);
}
Lay->FirstUndoVisFldInfo = NULL;
OffMenu(CurrentPro->CurrentLayout->Window, FULLMENUNUM(1,0,NOSUB)); /* Edit->Undo */
return 0;
}
Bool PerformUndo(struct Layout *Lay)
{
struct VisFldInfo *tmp;
if (!Lay->FirstUndoVisFldInfo) return FALSE;
tmp = Lay->FirstVisFldInfo;
Lay->FirstVisFldInfo = Lay->FirstUndoVisFldInfo;
Lay->FirstUndoVisFldInfo = tmp;
Crsr.vf = Lay->FirstVisFldInfo;
Selected = NULL;
return TRUE;
}
Bool SaveUndo(struct Layout *Lay)
{
struct VisFldInfo *vf, **link_here;
DeleteUndo(Lay); /* Remove old undo */
link_here = &Lay->FirstUndoVisFldInfo;
for (vf = Lay->FirstVisFldInfo; vf; vf=vf->Next, link_here = &((*link_here)->Next)) {
if (!(*link_here = CopyVisFldInfo(vf))) return DeleteUndo(Lay);
}
OnMenu(CurrentPro->CurrentLayout->Window, FULLMENUNUM(1,0,NOSUB)); /* Edit->Undo */
CurrentPro->Modified |= PROMODIFIED;
return TRUE;
}
static int Redraw(struct Pro *Pr, struct Layout *Lay)
{
/* Recalculates all gadgets and redraws the updated window */
WORD ww, wh;
WORD x,y;
int ret;
Bool ok = TRUE;
/* Tear down */
DisplayCursor(Lay->Window->RPort, -1, -1);
Rubberband(Lay->Window->RPort, -1, -1, -1, -1, 0);
/* Rebuild with undo fallback */
do {
if ((ret = CalcAllPos(Pr, Lay, &ww, &wh)) >= 0) {
if ((ret = CreateAllGadgets(Pr, Lay, ww, wh, DESIGN_MODE)) >= 0) {
if ((ret = AttachAllGadgets(Lay, ww, wh, DESIGN_MODE)) >= 0) {
DeleteAllGadgets(Lay, DESIGN_MODE);
GetCursorPosition(&Crsr, &x, &y);
DisplayCursor(Lay->Window->RPort, x, y);
SelectVisFld(Lay, Selected); /* Update rubberband */
/* Update pointer */
if (SizeHit(VisFldHit(Lay, DB_Msg.MouseX, DB_Msg.MouseY), DB_Msg.MouseX))
ChangePointer(Lay->Window, LRPointer);
else RestorePointer(Lay->Window);
return ret;
}
}
DeleteAllGadgets(Lay, DESIGN_MODE);
}
DisplayBeep(Scr);
ok = PerformUndo(Lay);
DeleteUndo(Lay);
} while (ok);
return ret; /* This is serious trouble */
}
int DoEdit(struct Pro *Pr, struct VisFldInfo *vf)
{
/* Let the user perform the actual editing of a vf */
/* returns 0 if no changes has been made to vf */
struct FldInfo *f;
BOOL quit = FALSE;
if (OpenVisWindow()) return 0;
/* Prepare gadgets */
GT_SetGadgetAttrs(VisGadgets[GD_VIS_NAME], VisWnd, NULL,
GTST_String, vf->Name,
TAG_END);
GT_SetGadgetAttrs(VisGadgets[GD_VIS_SIZE], VisWnd, NULL,
GTIN_Number, vf->VisLen,
TAG_END);
if (f = GetFldInfo(Pr, vf->Offset))
GT_SetGadgetAttrs(VisGadgets[GD_VIS_FIELD], VisWnd, NULL,
GTTX_Text, f->Name,
TAG_END);
else GT_SetGadgetAttrs(VisGadgets[GD_VIS_FIELD], VisWnd, NULL,
GTTX_Text, "<Select field>",
TAG_END);
Vf = vf; /* GadTooBox handlers use global variables */
/* Handle input */
while (!quit) {
WaitPort(VisWnd->UserPort);
quit = HandleVisIDCMP();
}
CloseVisWindow(); /* GadToolBox automatically NULLs pointers */
if (quit == RET_CANCEL) return 0;
/* update vf */
strcpy(vf->Name, GetString(VisGadgets[GD_VIS_NAME]));
vf->VisLen = GetNumber(VisGadgets[GD_VIS_SIZE]);
WriteVisTags(vf); /* Update RFF tags in vf */
/* As user might have connected the vf to an internal field of cycle type,
* we must then remake the cycle list by reading the VisTags
*/
if (ReadVisTags(Pr, vf) < 0) return 0;
/* vf->Offset and the tags has been updated inside GadToolBox */
return 1; /* Use */
}
void ReplaceVisFldInfo(struct Layout *Lay, struct VisFldInfo *old, struct VisFldInfo *new)
{
struct VisFldInfo *prev = PrevVisFldInfo(Lay, old);
new->Next = old->Next;
if (prev) prev->Next = new;
else Lay->FirstVisFldInfo = new;
/* Don't forget to make sure that the cursor and rubberband points correctly */
if (Crsr.vf == old) Crsr.vf = new;
if (Selected == old) Selected = new;
}
static void EditVisFldInfo(struct Pro *Pr, struct Layout *Lay, struct VisFldInfo *vf)
{
struct VisFldInfo *copy = CopyVisFldInfo(vf);
if (!copy) return;
for (;;) {
if (!DoEdit(Pr, copy)) { /* Cancel */
DeleteVisFldInfo(copy);
Redraw(Pr, Lay);
return;
}
else {
ReplaceVisFldInfo(Lay, vf, copy);
if (Redraw(Pr, Lay) < 0) { /* Oops, this didn't fit on screen */
ReplaceVisFldInfo(Lay, copy, vf);
}
else break;
}
}
DeleteVisFldInfo(vf);
}
/**********************************************************************/
/* Event handlers */
/**********************************************************************/
static void CloseDesignWin(struct Layout *Lay)
{
if (Lay->Window) {
DisplayCursor(Lay->Window->RPort, -1, -1); /* Remove cursor */
Rubberband(Lay->Window->RPort, -1, -1, -1, -1, 0); /* Remove rubberband */
/* Remember old window pos */
LastLeftEdge = Lay->Window->LeftEdge;
LastTopEdge = Lay->Window->TopEdge;
ClearMenuStrip(Lay->Window);
FreeMenus( DesignMenus );
DesignMenus = NULL;
CloseWindow(Lay->Window);
Lay->Window = NULL;
}
}
static int RawKey(struct Pro *Pr, struct Layout *Lay)
{
WORD x,y;
WORD oldx,oldy;
struct VisFldInfo *oldpos = Crsr.vf;
switch (DB_Msg.Code) {
/* case RAW_F10:
Redraw(Pr, Lay);
return 0;
break; // Looks nice :-)
case RAW_F10-3:
DeleteUndo(Lay);
printf("DeleteUndo\n");
break;
case RAW_F10-2:
SaveUndo(Lay);
printf("Save\n");
break;
case RAW_F10-1:
PerformUndo(Lay);
Redraw(Pr, Lay);
break;
*/
case RAW_HELP:
EasyRequest(Lay->Window, &ES_ViewDesignHelp, NULL);
break;
case RAW_LEFT:
PreviousPosition(Lay, &Crsr);
break;
case RAW_RIGHT:
NextPosition(Lay, &Crsr);
break;
case RAW_UP:
GetCursorPosition(&Crsr, &oldx, &oldy);
while (PreviousPosition(Lay, &Crsr)) {
GetCursorPosition(&Crsr, &x, &y);
if (y < oldy && x <= oldx) break;
}
break;
case RAW_DOWN:
GetCursorPosition(&Crsr, &oldx, &oldy);
while (NextPosition(Lay, &Crsr)) {
GetCursorPosition(&Crsr, &x, &y);
if (y > oldy) {
oldy = y;
break;
}
}
while (NextPosition(Lay, &Crsr)) {
GetCursorPosition(&Crsr, &x, &y);
if (y > oldy || x > oldx) {
PreviousPosition(Lay, &Crsr);
break;
}
}
break;
}
GetCursorPosition(&Crsr, &x, &y);
DisplayCursor(Lay->Window->RPort, x, y);
if (Crsr.vf != oldpos) SelectVisFld(Lay, NULL); /* Cursor has moved, so clear rubberband */
return 0;
}
static int VanillaKey(struct Pro *Pr, struct Layout *Lay)
{
struct VisFldInfo *vf = NULL;
char oldVisSep;
SaveUndo(Lay);
switch (DB_Msg.Code) {
case '\r':
if (Crsr.after) vf = Crsr.vf;
else vf = PrevVisFldInfo(Lay, Crsr.vf);
if (!vf) break;
oldVisSep = vf->VisSep;
switch (vf->VisSep) {
case ' ':
case '\t':
vf->VisSep = '\n';
break;
case '\n':
vf->VisSep = '\f';
break;
}
break;
case '\t':
if (Crsr.after) vf = Crsr.vf;
else vf = PrevVisFldInfo(Lay, Crsr.vf);
if (!vf) break;
oldVisSep = vf->VisSep;
if (vf->VisSep == ' ') {
vf->VisSep = '\t';
}
break;
case '\b':
if (Crsr.after) break;
else vf = PrevVisFldInfo(Lay, Crsr.vf);
if (!vf) break;
oldVisSep = vf->VisSep;
switch (vf->VisSep) {
case '\t':
case '\n':
vf->VisSep = ' ';
break;
case '\f':
vf->VisSep = '\n';
break;
}
break;
case VANILLA_DEL:
if (Selected) { /* Delete the selected field */
SaveUndo(Lay);
DeleteVisFldInfo(RemoveVisFldInfo(Lay, Selected));
Redraw(Pr, Lay);
return 0;
}
else {
if (!Crsr.after) break;
else vf = Crsr.vf;
if (!vf) break;
oldVisSep = vf->VisSep;
switch (vf->VisSep) {
case '\t':
case '\n':
vf->VisSep = ' ';
break;
case '\f':
vf->VisSep = '\n';
break;
}
}
break;
case VANILLA_ESC:
return 1; /* Exit design mode */
break;
}
if (vf && vf->VisSep != oldVisSep) {
if (Redraw(Pr, Lay) < 0) { /* Oops, this didn't fit on screen */
DisplayBeep(Scr);
vf->VisSep = oldVisSep;
if (Redraw(Pr, Lay) < 0) ByeBye(); /* This should never happen */
}
WriteVisTags(vf); /* Update RFF tags in vf */
}
return 0;
}
int MouseButtons(struct Pro *Pr, struct Layout *Lay)
{
static ULONG StartSeconds=0, StartMicros=0;
struct VisFldInfo *oldselected = Selected;
if (Selected = VisFldHit(Lay, DB_Msg.MouseX, DB_Msg.MouseY)) {
struct Space *sp = &Selected->Pos;
Rubberband(Lay->Window->RPort, sp->XOffset, sp->YOffset, sp->Width, sp->Height, 0);
if (DoubleClick(StartSeconds, StartMicros, DB_Msg.Seconds, DB_Msg.Micros) &&
Selected == oldselected) {
if (DragCnt) { /* Cancel dragging */
DragCnt = 0;
RestorePointer(Lay->Window);
}
EditVisFldInfo(Pr, Lay, Selected);
StartSeconds = StartMicros = 0; /* Prevent "triple clicks" */
}
else {
StartSeconds = DB_Msg.Seconds; StartMicros = DB_Msg.Micros;
if (Selected) {
if (SizeHit(Selected, DB_Msg.MouseX)) {
Sizing = TRUE;
Forbid();
Lay->Window->Flags |= WFLG_RMBTRAP;
Permit();
}
else DragCnt = 1; /* Initiate dragging */
}
}
}
else {
Rubberband(Lay->Window->RPort, -1, -1, -1, -1, 0);
FollowMouse(Lay, DB_Msg.MouseX, DB_Msg.MouseY);
}
return 0;
}
static void ToolBoxClicked(struct Pro *Pr, struct Layout *Lay, int gadgetID)
{
struct VisFldInfo *vf;
/* Make a VisFldInfo */
if (!(vf = NewVisFldInfo())) return;
/* Fill in type (string, cycle or checkbox) */
switch (gadgetID) {
case CheckBoxID:
CreateAndAddTag(&vf->VisTags, FTYP, STR_CHECKBOX);
vf->VisLen = 3; /* smaller is better */
break;
case CycleID:
CreateAndAddTag(&vf->VisTags, FTYP, STR_CYCLE);
CreateAndAddTag(&vf->VisTags, CENT, "Apples");
CreateAndAddTag(&vf->VisTags, CENT, "Pears");
CreateAndAddTag(&vf->VisTags, CENT, "Bananas");
vf->VisLen = 16; /* smaller is better */
break;
}
ReadVisTags(Pr, vf); /* This way we get the cycle-list in vf */
vf->Name[0] = '\0';
/* Release the user */
if (!DoEdit(Pr, vf)) { /* Cancel */
DeleteVisFldInfo(vf);
return;
}
InsertVisFldInfo(Lay, vf); /* link it */
if (Redraw(Pr, Lay) < 0) { /* Oops, this didn't fit on screen */
DisplayBeep(Scr);
DeleteVisFldInfo(RemoveVisFldInfo(Lay, vf));
Redraw(Pr, Lay);
}
if (!Crsr.vf) Crsr.vf = Lay->FirstVisFldInfo; /* Move cursor on-track */
}
/**********************************************************************/
/* IDCMP handler */
/**********************************************************************/
static int DesignWindowIDCMP(struct Pro *Pr, struct Layout *Lay)
{
struct IntuiMessage *m;
struct MenuItem *n;
int (*func)(void);
struct Window *Win = Lay->Window;
ULONG signals, winsig, toolboxsig = 0;
BOOL running = TRUE;
winsig = 1L << Win->UserPort->mp_SigBit;
if (ToolBox) toolboxsig = 1L << ToolBox->UserPort->mp_SigBit;
for (;;) {
// WaitPort(Win->UserPort);
signals = Wait(winsig | toolboxsig);
if (signals & winsig) {
while( m = GT_GetIMsg( Win->UserPort )) {
CopyMem(( char * )m, ( char * )&DB_Msg, (long)sizeof( struct IntuiMessage ));
GT_ReplyIMsg( m );
switch ( DB_Msg.Class ) {
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh(Win);
GT_EndRefresh(Win, TRUE );
break;
case IDCMP_CLOSEWINDOW:
return 0;
break;
case IDCMP_NEWSIZE:
// // printf("IDCMP_NEWSIZE\n");
if (!(Win->Flags & WFLG_ZOOMED)) Redraw(Pr, Lay);
break;
case IDCMP_VANILLAKEY:
// // printf("IDCMP_VANILLAKEY\n");
running = VanillaKey(Pr, Lay);
if (running) return running;
break;
case IDCMP_RAWKEY:
// // printf("IDCMP_RAWKEY\n");
running = RawKey(Pr, Lay);
break;
case IDCMP_MOUSEMOVE:
{
if (Sizing) {
Selected->Pos.Width = DB_Msg.MouseX - Selected->Pos.XOffset;
FLOOR(Selected->Pos.Width, FontX+STRGADFRAMESWIDTH);
SelectVisFld(Lay, Selected); /* Update rubberband */
break;
}
else if (DragCnt) {
if (DragCnt++ == DRAGTRESHOLD) {
ChangePointer(Win, MovePointer);
Forbid();
Win->Flags |= WFLG_RMBTRAP;
Permit();
}
FollowMouse(Lay, DB_Msg.MouseX, DB_Msg.MouseY);
}
else if (SizeHit(VisFldHit(Lay, DB_Msg.MouseX, DB_Msg.MouseY), DB_Msg.MouseX))
ChangePointer(Win, LRPointer);
else RestorePointer(Win);
}
// printf("IDCMP_MOUSEMOVE\n");
break;
case IDCMP_MOUSEBUTTONS:
if (DB_Msg.Code == SELECTDOWN) {
running = MouseButtons(Pr, Lay);
}
else if (DB_Msg.Code == SELECTUP) {
if (Win->Flags & WFLG_RMBTRAP) { /* Enable menu button again */
Forbid();
Win->Flags &= ~WFLG_RMBTRAP;
Permit();
}
if (DragCnt >= DRAGTRESHOLD) {
RestorePointer(Win);
if (Crsr.vf != Selected) { /* Move it */
SaveUndo(Lay);
InsertVisFldInfo(Lay, RemoveVisFldInfo(Lay, Selected));
Redraw(Pr, Lay);
}
}
else if (Sizing) {
Sizing = FALSE;
SaveUndo(Lay);
Selected->VisLen = (Selected->Pos.Width+(FontX+1)/2-STRGADFRAMESWIDTH)/FontX;
WriteVisTags(Selected); /* Update RFF tags in vf */
Redraw(Pr, Lay);
}
DragCnt = 0;
}
else if (DB_Msg.Code == MENUUP) { /* Cancel */
if (Win->Flags & WFLG_RMBTRAP) { /* Enable menu button again */
Forbid();
Win->Flags &= ~WFLG_RMBTRAP;
Permit();
}
if (DragCnt) { /* Cancel dragging */
DragCnt = 0;
RestorePointer(Win);
}
else if (Sizing) { /* Cancel sizechange */
Sizing = FALSE;
Redraw(Pr, Lay);
}
}
break;
case IDCMP_MENUPICK:
while( DB_Msg.Code != MENUNULL ) {
n = ItemAddress( Win->MenuStrip, DB_Msg.Code );
func = (int (*)(void))(GTMENUITEM_USERDATA( n ));
running = func();
if (running) return running; /* The window has been closed! */
DB_Msg.Code = n->NextSelect;
}
break;
}
}
} /* winsig signals */
if (signals & toolboxsig) {
while( m = GT_GetIMsg( ToolBox->UserPort )) {
CopyMem(( char * )m, ( char * )&DB_Msg, (long)sizeof( struct IntuiMessage ));
GT_ReplyIMsg( m );
switch ( DB_Msg.Class ) {
case IDCMP_GADGETUP:
// printf("Gadget up\n");
ActivateWindow(Win);
ToolBoxClicked(Pr, Lay, ((struct Gadget *)DB_Msg.IAddress)->GadgetID);
break;
}
}
} /* toolbox signals */
}
return( running );
}
static int DoOpenDesignWindow(struct Pro *Pr, struct Layout *Lay, WORD ww, WORD wh)
{
/* Does the actual opening (in DESIGN_MODE) */
WORD leftedge, topedge;
/* Position window nicely */
if (LastLeftEdge == -1) { /* No previous window to use */
leftedge = (Scr->Width - ww) >> 1; /* Middle */
topedge = (Scr->Height-wh) >> 1; /* Middle */
}
else {
leftedge = LastLeftEdge;
topedge = LastTopEdge;
}
/* We create this menu every time we enter view design */
if ( ! ( DesignMenus = CreateMenus( DesignNewMenu, TAG_DONE )))
return( 3L );
LayoutMenus( DesignMenus, VisualInfo, GTMN_NewLookMenus, TRUE, TAG_DONE );
if ( ! ( Lay->Window = OpenWindowTags( NULL,
WA_Left, leftedge,
WA_Top, topedge,
WA_Width, ww,
WA_Height, wh,
WA_IDCMP, IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE|IDCMP_NEWSIZE|IDCMP_MENUPICK|IDCMP_CLOSEWINDOW|IDCMP_RAWKEY|IDCMP_VANILLAKEY|IDCMP_REFRESHWINDOW,
WA_Flags, WFLG_REPORTMOUSE|WFLG_NEWLOOKMENUS|WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
WA_Gadgets, Lay->GList,
WA_Title, "Move the cursor and design!",
WA_ScreenTitle, "db v" VERSION_NUMBER " View design",
WA_PubScreen, Scr,
WA_Zoom, DB_Zoom,
// WA_MenuHelp, TRUE,
TAG_DONE )))
return WIN_ERR;
SetMenuStrip( Lay->Window, DesignMenus );
GT_RefreshWindow( Lay->Window, NULL);
/* Now detach all gadgets from the window as this is the design mode */
RemoveGList(Lay->Window, Lay->GList, -1);
/* We delete the gadgets and just leave the imagery */
DeleteAllGadgets(Lay, DESIGN_MODE);
/* For IDCMP handling used in this file */
WinSig = 1L << Lay->Window->UserPort->mp_SigBit;
return 0;
}
void FillClip(struct VisFldInfo *vf)
{
if (Clip) {
DeleteVisFldInfo(Clip);
}
Clip = vf;
}
/**********************************************************************/
/* Interface functions */
/**********************************************************************/
void Design(struct Pro *Pr, struct Layout *Lay)
{
/* This is the main function in the design system */
WORD ww, wh;
WORD x,y;
/* ww = Lay->Window->Width;
wh = Lay->Window->Height;
*/
CloseLayWin(Pr, Lay);
CalcAllPos(Pr, Lay, &ww, &wh); // Shouldn't be nessesary as we reopen the window
CreateAllGadgets(Pr, Lay, ww, wh, DESIGN_MODE);
DoOpenDesignWindow(Pr, Lay, ww, wh);
InitCursor(Lay, &Crsr);
Selected = NULL;
GetCursorPosition(&Crsr, &x, &y);
DisplayCursor(Lay->Window->RPort, x, y);
ToolBox = OpenToolBox(Lay->Window); /* "Parent" window */
DesignWindowIDCMP(Pr, Lay);
DeleteUndo(Lay);
FillClip(NULL);
CloseDesignWin(Lay);
if (ToolBox) {
CloseToolBox(ToolBox);
ToolBox = NULL;
}
OpenLayWin(Pr, Lay);
UpdateWindow(Pr);
UpdateDragBar(Pr);
/* Back to db run-mode */
}
/**********************************************************************/
/* GadToolBox handlers */
/**********************************************************************/
int LISTClicked( void )
{
/* routine when gadget "Object list" is clicked. */
return 0;
}
int TOPClicked( void )
{
/* routine when gadget "Top" is clicked. */
return 0;
}
int UPClicked( void )
{
/* routine when gadget "Up" is clicked. */
return 0;
}
int DOWNClicked( void )
{
/* routine when gadget "Down" is clicked. */
return 0;
}
int BOTTOMClicked( void )
{
/* routine when gadget "Bottom" is clicked. */
return 0;
}
int NEWClicked( void )
{
/* routine when gadget "_New..." is clicked. */
return 0;
}
int EDITClicked( void )
{
/* routine when gadget "_Edit..." is clicked. */
return 0;
}
int COPYClicked( void )
{
/* routine when gadget "Co_py" is clicked. */
return 0;
}
int REMOVEClicked( void )
{
/* routine when gadget "Remove" is clicked. */
return 0;
}
int USEClicked( void )
{
/* routine when gadget "_Use" is clicked. */
return 0;
}
int CANCELClicked( void )
{
/* routine when gadget "_Cancel" is clicked. */
return 0;
}
int TAG_VALUEClicked( void )
{
/* routine when gadget "_Value" is clicked. */
return 0;
}
int TAG_IDClicked( void )
{
/* routine when gadget "_ID" is clicked. */
return 0;
}
int TAG_OKClicked( void )
{
/* routine when gadget "_Ok" is clicked. */
return 0;
}
int TAG_CANCELClicked( void )
{
/* routine when gadget "_Cancel" is clicked. */
return 0;
}
int NAME_NAMEClicked( void )
{
/* routine when gadget "_Name" is clicked. */
return 0;
}
int NAME_OKClicked( void )
{
/* routine when gadget "_Ok" is clicked. */
return 0;
}
int NAME_CANCELClicked( void )
{
/* routine when gadget "_Cancel" is clicked. */
return 0;
}
int FIELD_NAMEClicked( void )
{
/* routine when gadget "_Name" is clicked. */
return 0;
}
int FIELD_MAXLENClicked( void )
{
/* routine when gadget "Max _length" is clicked. */
return 0;
}
int FIELD_OKClicked( void )
{
/* routine when gadget "_Ok" is clicked. */
return 0;
}
int FIELD_CANCELClicked( void )
{
/* routine when gadget "_Cancel" is clicked. */
return 0;
}
int FIELD_MOREClicked( void )
{
/* routine when gadget "_More..." is clicked. */
return 0;
}
int VIS_NAMEClicked( void )
{
/* routine when gadget "_Name" is clicked. */
return 0;
}
int VIS_SIZEClicked( void )
{
/* routine when gadget "Si_ze" is clicked. */
return 0;
}
int VIS_OKClicked( void )
{
/* routine when gadget "_Ok" is clicked. */
return RET_OK;
}
int VIS_CANCELClicked( void )
{
/* routine when gadget "_Cancel" is clicked. */
return RET_CANCEL;
}
int VIS_MOREClicked( void )
{
/* routine when gadget "_More..." is clicked. */
return 0;
}
int VIS_SELECTClicked( void )
{
/* routine when gadget "..." is clicked. */
Select *s;
struct FldInfo *f;
BOOL again = TRUE;
if (!(s = NewSelect())) {
DisplayBeep(Scr);
return 0;
}
for (f = CurrentPro->FirstFldInfo; f; f = f->Next)
AddStringLast(s, f->Name);
s->SelIndex = Vf->Offset;
OpenSelect(s, VisWnd, "Select field", NULL);
while (again) {
WaitPort(s->SelWnd->UserPort);
switch(HandleSelectIDCMP(s)) {
case SEL_SELECT :
break;
case SEL_OK :
Vf->Offset = s->SelIndex;
GT_SetGadgetAttrs(VisGadgets[GD_VIS_FIELD], VisWnd, NULL,
GTTX_Text, SelectedString(s),
TAG_END);
again = FALSE;
break;
case SEL_CANCEL :
again = FALSE;
break;
case SEL_HELP :
break;
}
}
/* CloseSelect(s);
RemoveAllStrings(s);
*/
DeleteSelect(s);
return 0;
}
int MainCloseWindow( void )
{
/* routine for "IDCMP_CLOSEWINDOW". */
return 1; /* i.e. Leave this mode */
}
int MainVanillaKey( void )
{
/* routine for "IDCMP_VANILLAKEY". */
return 0;
}
int MainRawKey( void )
{
/* routine for "IDCMP_RAWKEY". */
return 0;
}
int TagCloseWindow( void )
{
/* routine for "IDCMP_CLOSEWINDOW". */
return 0;
}
int TagVanillaKey( void )
{
/* routine for "IDCMP_VANILLAKEY". */
return 0;
}
int NameCloseWindow( void )
{
/* routine for "IDCMP_CLOSEWINDOW". */
return 0;
}
int NameVanillaKey( void )
{
/* routine for "IDCMP_VANILLAKEY". */
return 0;
}
int FieldCloseWindow( void )
{
/* routine for "IDCMP_CLOSEWINDOW". */
return 0;
}
int FieldVanillaKey( void )
{
/* routine for "IDCMP_VANILLAKEY". */
return 0;
}
int VisCloseWindow( void )
{
/* routine for "IDCMP_CLOSEWINDOW". */
return RET_CANCEL;
}
int VisVanillaKey( void )
{
/* routine for "IDCMP_VANILLAKEY". */
switch (ToUpper(VisMsg.Code)) {
case 'N':
ActivateGadget(VisGadgets[GD_VIS_NAME], VisWnd, NULL);
break;
case 'Z':
ActivateGadget(VisGadgets[GD_VIS_SIZE], VisWnd, NULL);
break;
case 'O':
case '\r':
return VIS_OKClicked();
break;
case 'C':
case VANILLA_ESC:
return VIS_CANCELClicked();
break;
}
return 0;
}
int DesignPROJECT_ABOUT( void )
{
/* routine when (sub)item "About view design..." is selected. */
EasyRequest(CurrentPro->CurrentLayout->Window, &ES_ViewDesignHelp, NULL);
return 0;
}
int DesignPROJECT_EXIT( void )
{
/* routine when (sub)item "Exit view design" is selected. */
return 1; /* Leave View design */
}
int DesignEDIT_UNDO( void )
{
/* routine when (sub)item "Undo" is selected. */
if (PerformUndo(CurrentPro->CurrentLayout))
Redraw(CurrentPro, CurrentPro->CurrentLayout);
else DisplayBeep(Scr);
return 0;
}
int DesignEDIT_CUT( void )
{
/* routine when (sub)item "Cut" is selected. */
if (Selected) {
SaveUndo(CurrentPro->CurrentLayout);
FillClip(RemoveVisFldInfo(CurrentPro->CurrentLayout, Selected));
OnMenu(CurrentPro->CurrentLayout->Window, FULLMENUNUM(1,4,NOSUB)); /* Edit->Paste */
Redraw(CurrentPro, CurrentPro->CurrentLayout);
}
return 0;
}
int DesignEDIT_COPY( void )
{
/* routine when (sub)item "Copy" is selected. */
if (Selected) {
FillClip(CopyVisFldInfo(Selected));
OnMenu(CurrentPro->CurrentLayout->Window, FULLMENUNUM(1,4,NOSUB)); /* Edit->Paste */
}
return 0;
}
int DesignEDIT_PASTE( void )
{
/* routine when (sub)item "Paste" is selected. */
SaveUndo(CurrentPro->CurrentLayout);
InsertVisFldInfo(CurrentPro->CurrentLayout, CopyVisFldInfo(Clip));
Redraw(CurrentPro, CurrentPro->CurrentLayout);
return 0;
}